import { useSceneStore } from '@/store/scene';
import { addParticle, addlayerRequestIns, updateDom } from '@/service/effect';
import { createVNode, render } from 'vue';
import PanelTag from '@/components/gis-div/panel-poi.vue';
import { getNodeByTree, retFilePath } from '@/utils';
import { round } from 'lodash';

// 图层
const layerMap = new Map();
// 模型加载
const modelReadyMap = new Map();

export type tagType = 'panelTag';

const L00 = [1.234709620475769, 1.221461296081543, 1.273156881332397];
const L1_1 = [1.135921120643616, 1.171217799186707, 1.287644743919373];
const L10 = [1.245193719863892, 1.245591878890991, 1.282818794250488];
const L11 = [-1.106930732727051, -1.112522482872009, -1.153198838233948];
const L2_2 = [-1.086226940155029, -1.079731941223145, -1.101912498474121];
const L2_1 = [1.189834713935852, 1.185906887054443, 1.214385271072388];
const L20 = [0.01778045296669, 0.02013735473156, 0.025313569232821];
const L21 = [-1.086826920509338, -1.084611177444458, -1.111204028129578];
const L22 = [-0.05241484940052, -0.048303380608559, -0.041960217058659];
const coefficients = [L00, L1_1, L10, L11, L2_2, L2_1, L20, L21, L22];

/**
 * 获取场景服务
 * @returns
 */
export const getService = (): Promise<any> => {
  return new Promise<any>((resolve) => {
    tryGetService(resolve);
  });
};

const tryGetService = (resolve: (arg: any) => void) => {
  const { isCimupComplete } = useSceneStore();
  if (isCimupComplete) {
    resolve(true);
    return;
  }
  setTimeout(() => {
    return tryGetService(resolve);
  }, 1000);
};

export const createBasicElement = (vueDom: any, param: any, type: tagType, specialTag?: string) => {
  const vmInstance = createVNode(vueDom, { data: param });
  const mountNode = document.createElement('div');
  let className = `gis-container-web-div ${type}`;
  if (specialTag) {
    className += ` ${specialTag}`;
  }
  mountNode.className = className;
  render(vmInstance, mountNode);
  const dom: any = document.getElementById('cesiumContainer');
  dom.appendChild(mountNode);
  return mountNode;
};

// 添加图层
export const addLayer = (layer: API.Scene.ILayer) => {
  const { cimInstance } = window;
  if (['imageLayer'].includes(layer.type)) {
    cimInstance.api.addImageLayer(layer.json);
    return;
  }
  if (layer.type === 'gltfmodel') {
    const param = {
      ...layer.json,
      readyCall: importModelCallBack,
    };
    if (layer.actualType !== 'gltfmodeleffect') {
      param.enablePbr = true;
      param.iblConfig = {
        coefficients: coefficients,
        environmentMaps: retFilePath('comm/public/ktx/city_morning.ktx2'),
      };
    }
    cimInstance.api.addGLTFModel(param);
    return;
  }
  if (['entity', 'fake_particleSystem'].includes(layer.type)) {
    // layer.json.views[0].readyCall = importModelCallBack;
    modelReadyMap.set(layer.layerName, true);
    cimInstance.entityApi.addEntity(layer.json);
    return;
  }
  if (layer.type === 'drawlabel') {
    cimInstance.api.startDrawLabel(layer.json);
    modelReadyMap.set(layer.layerName, true);
    return;
  }
  if (['road', 'regionEffect'].includes(layer.type)) {
    modelReadyMap.set(layer.layerName, true);
  }
  if (['tileset'].includes(layer.type)) {
    cimInstance.api.add3DTilesModel(layer.json);
    return;
  }
  if (['point'].includes(layer.type)) {
    cimInstance.api.addPointLayer(layer.json);
    return;
  }
  if (['polyline'].includes(layer.type)) {
    cimInstance.api.addPolylineLayer(layer.json);
    return;
  }
  if (['polygon'].includes(layer.type)) {
    cimInstance.api.addPolygonLayer(layer.json);
    return;
  }
  if (layer.type === 'bimModel') {
    cimInstance.api.addLayerByType({
      ...layer.json,
      loadConfig: [
        {
          title: '',
          url: layer.json.url,
          texturePath: layer.json.texturePath,
          translation: layer.json.translation,
          unit: 'm',
          rotation: layer.json.rotation,
          scale: 1,
          useMaterial: true,
        },
      ],
    });
    return;
  }
  if (['image'].includes(layer.type)) {
    console.log('---执行了---', layer.type, layer.json);
    cimInstance.api.addLayerByType(layer.json);
  }
  if (['terrain'].includes(layer.type)) {
    cimInstance.api.addLayerByType(layer.json);
  }
};

// 销毁图层
export const destroyLayer = (layer: API.Scene.ILayer) => {
  const { cimInstance } = window;
  if (layer.type === 'div') {
    const targetAllDom: any = document.querySelectorAll(`.${layer.layerName}`);
    targetAllDom.forEach((dom: any) => {
      render(null, dom);
      dom.parentNode.removeChild(dom);
    });
    return;
  }
  if (layer.json.type && layer.json.type === 'entity') {
    cimInstance.entityApi.removeEntity(layer.layerName);
    return;
  }
  cimInstance.api.destroyLayer(layer.layerName);
};

// 图层隐藏显示
export const setLayerVisible = (layer: API.Scene.ILayer) => {
  const { cimInstance } = window;
  if (layer.type === 'div') {
    updateDom(layer);
  } else {
    cimInstance.api.setLayerVisible(layer.layerName, layer.show);
  }
};

// 模型加载回调
export const importModelCallBack = (layer: any) => {
  const { layerList } = useSceneStore();
  console.log(`${layer.name}---加载完成`);
  modelReadyMap.set(layer.name, true);
  layerList
    .filter((item: API.Scene.ILayer) => item.layerName === layer.name)
    .forEach((item: API.Scene.ILayer) => {
      setLayerVisible(item);
      // 加载特效
      if (item.effect) {
        if (item.type === 'gltfmodel') {
          item.effect.list.forEach((v: any) => {
            addParticle(v, item.effect!.requestData, item.layerName);
          });
        }
        addlayerRequestIns(item);
      }
    });
};

export const callBackZoomTo = (layer: any) => {
  const { cimInstance } = window;
  if (['div'].includes(layer.type)) {
    const params = cimInstance.api.getCameraParameter();
    cimInstance.api.lookModel(
      layer.attr.position[0],
      layer.attr.position[1],
      layer.attr.position[2],
      params.heading,
      params.patch,
      100,
      0.7
    );
    return;
  }
  cimInstance.api.zoomToLayer(layer.name);
};

export const getModelReadyMap = () => {
  return modelReadyMap;
};

export const clearModelReadyMap = () => {
  modelReadyMap.clear();
};

export const getLayerMap = () => {
  return layerMap;
};

export const clearLayerMap = () => {
  layerMap.clear();
};

// 添加面板标识
export const addPanelTag = (data: any) => {
  const { cimInstance } = window;
  const mountNode = createBasicElement(PanelTag, data, 'panelTag', data.layerName);
  cimInstance.api.setDiv(mountNode, {
    degreesPosition: {
      longitude: data.longitude,
      latitude: data.latitude,
      height: data.height,
    },
  });
};

// 所有图层创建点击回调事件
const layerClickCallbackMap = new Map();

export const createLayerClickCallbackEvent = (layer: API.Scene.ILayer) => {
  const { cimInstance } = window;
  if (!layerClickCallbackMap.get(layer.code)) {
    console.log('挂载图层点击事件---', layer.layerName);
    if (layer.type === 'drawlabel') {
      cimInstance.api.addLayerEventListener(layer.layerName, 'mouse_leftclick', poiClickCallback);
      layerClickCallbackMap.set(layer.code, layer.code);
      return;
    }
    if (layer.type === 'regionEffect') {
      cimInstance.api.addLayerEventListener(
        layer.layerName,
        'mouse_leftclick',
        regionEffectClickCallback
      );
      layerClickCallbackMap.set(layer.code, layer.code);
      return;
    }
    if (layer.type === 'road') {
      cimInstance.api.addLayerEventListener(
        layer.layerName,
        'mouse_leftclick',
        roadEffectClickCallback
      );
      layerClickCallbackMap.set(layer.code, layer.code);
    }
  }
};

// poi图层点击回调事件
export const poiClickCallback = (e: any) => {
  const { cimInstance, Cesium } = window;
  if (!e.clickObject) return;
  const sceneStore = useSceneStore();
  // TODO 此处暂时这么判断
  if (sceneStore.effectDotState && !e.code) return;
  if (sceneStore.selLayer) {
    destroyOrbitControl(sceneStore.selLayer);
  }
  const layerName = e.clickObject.layerName || e.clickObject.properties.layerName.getValue();
  // const result = cimInstance.api.getGraphicInfo(layerName, 'poi_0_image', {
  //   properties: true,
  // });
  // const properties = result.properties.getValue(new Cesium.JulianDate());
  const properties = cimInstance.api.getLayer(layerName).geojsonData.features[0].properties;
  // 找到图层选中
  const targetLayer = getNodeByTree(layerName, sceneStore.layerTree);
  if (!targetLayer) return;
  sceneStore.selLayer = targetLayer;
  const infoFont = properties.infoFont;
  const attr = {
    entityId: properties.id + '_image',
    position: properties.coordinates,
    imageWidth: properties.imageWidth,
    imageHeight: properties.imageHeight,
    scaleByDistanceArray: properties.imageScaleByDistanceArray,
    heightReference:
      properties.imageHeightReference && properties.imageHeightReference === 'CLAMP_TO_GROUND',
    isBlink: properties.imageIsBlink,
    imageUrl: properties.imageUrl,
    infoValue: properties.infoValue,
    infoFont: infoFont.split('px')[0],
    infoFillColor: properties.infoFillColor,
    infoOffset: properties.infoOffset,
    infoVertical: properties.infoVertical,
    defaultShow: properties.defaultShow,
    imageMinDisplayDistance: properties.imageMinDisplayDistance,
    imageMaxDisplayDistance: properties.imageMaxDisplayDistance,
    infoMinDisplayDistance: properties.infoMinDisplayDistance,
    infoMaxDisplayDistance: properties.infoMaxDisplayDistance,
  };
  if (
    properties.imageMinDisplayDistance === 0 &&
    properties.infoMinDisplayDistance === 0 &&
    properties.imageMaxDisplayDistance === 10000 &&
    properties.infoMaxDisplayDistance === 10000
  ) {
    attr.defaultShow = false;
  }
  sceneStore.selLayer.attr = attr;
  cimInstance.api.setLayerOrbitControl(layerName, (backAttr: any) => {
    if (!sceneStore.selLayer.attr) return;
    sceneStore.selLayer.attr.position = [
      backAttr.cartographic.longitude,
      backAttr.cartographic.latitude,
      round(backAttr.cartographic.height, 2),
    ];
  });
  cimInstance.api.changeOrbitControlMode('translation');
  sceneStore.specialEffectVisible = true;
};

// 路径特效点击回调事件
export const roadEffectClickCallback = (e: any) => {
  const { cimInstance } = window;
  if (!e.clickObject) return;
  const sceneStore = useSceneStore();
  // TODO 此处暂时这么判断
  if (sceneStore.effectDotState && !e.code) return;
  const layerName = e.clickObject.id;
  if (!layerName) return;
  // 找到图层选中
  const targetLayer = getNodeByTree(layerName, sceneStore.layerTree);
  if (!targetLayer) return;
  sceneStore.selLayer = targetLayer;
  const { info } = cimInstance.api.getGraphicInfo(layerName, null, { info: true });
  const attr = {
    width: info.geomertyData.width,
    color: info.materialData.color,
    imageUrl: info.materialData.imageUrl,
    speed: info.materialData.speed,
  };
  sceneStore.selLayer.attr = attr;
  sceneStore.specialEffectVisible = true;
  // 图层设置为编辑样式
  // 只有当地图点击回调时才进入编辑模式
  !e.code && cimInstance.api.startEdit(layerName);
};

// 区域轮廓特效点击回调事件
export const regionEffectClickCallback = (e: any) => {
  const { cimInstance } = window;
  if (!e.clickObject) return;
  const sceneStore = useSceneStore();
  // TODO 此处暂时这么判断
  if (sceneStore.effectDotState && !e.code) return;
  const layerName = e.clickObject.id;
  if (!layerName) return;
  // 找到图层选中
  const targetLayer = getNodeByTree(layerName, sceneStore.layerTree);
  if (!targetLayer) return;
  sceneStore.selLayer = targetLayer;
  const { info } = cimInstance.api.getGraphicInfo(layerName, null, { info: true });
  const attr = {
    height: info.geomertyData.height,
    color: info.materialData.color,
    imageUrl: info.materialData.imageUrl,
    speed: info.materialData.speed,
    uvReversed: info.materialData.uvReversed,
    vFlow: info.materialData.vFlow,
  };
  sceneStore.selLayer.attr = attr;
  sceneStore.specialEffectVisible = true;
  // 图层设置为编辑样式
  // 只有当地图点击回调时才进入编辑模式
  !e.code && cimInstance.api.startEdit(layerName);
};

// 模型特效点击回调事件
export const gltfmodeleffectClickCallback = (e: any) => {
  const { cimInstance } = window;
  if (!e.clickObject) return;
  const sceneStore = useSceneStore();
  // 点击模型暂未实现
  // 主要用于特效打点立即弹出
  // TODO 此处暂时这么判断
  if (sceneStore.effectDotState && !e.code) return;
  if (sceneStore.selLayer) {
    destroyOrbitControl(sceneStore.selLayer);
  }
  const layerName = e.clickObject.id;
  const targetLayer = getNodeByTree(layerName, sceneStore.layerTree);
  if (!targetLayer) return;
  sceneStore.selLayer = targetLayer;
  if (!sceneStore.selLayer.attr) {
    sceneStore.selLayer.attr = {
      position: [0, 0, 0],
      scale: 0,
      scaleData: 0,
    };
  }
  cimInstance.api.setLayerOrbitControl(layerName, (backAttr: any) => {
    if (!sceneStore.selLayer.attr) return;
    const config = cimInstance.api.getCurrentLayerConfig(layerName);
    sceneStore.selLayer.attr.position = [
      backAttr.cartographic.longitude,
      backAttr.cartographic.latitude,
      round(backAttr.cartographic.height, 2),
    ];
    if (config?.scale) {
      sceneStore.selLayer.attr.scale = config.scale;
      sceneStore.selLayer.attr.scaleData = config.scale * 100;
    }
  });
  cimInstance.api.changeOrbitControlMode('translation');
  sceneStore.specialEffectVisible = true;
};

// 参数化特效点击回调事件
export const fakeparticleSystemEffectClickCallback = (e: any) => {
  const { cimInstance } = window;
  if (!e.clickObject) return;
  const sceneStore = useSceneStore();
  // 点击模型暂未实现
  // 主要用于特效打点立即弹出
  // TODO 此处暂时这么判断
  if (sceneStore.effectDotState && !e.code) return;
  if (sceneStore.selLayer) {
    destroyOrbitControl(sceneStore.selLayer);
  }
  const layerName = e.clickObject.id;
  const targetLayer = getNodeByTree(layerName, sceneStore.layerTree);
  if (!targetLayer) return;
  sceneStore.selLayer = targetLayer;
  const fakeLayer = cimInstance.api.getLayer(sceneStore.selLayer.json.components[0].name);
  const fakeLayerAttrs: any = fakeLayer.config;
  const attr: any = {
    position: [],
    rotation: [],
    semiMajorAxis: fakeLayerAttrs.semiMajorAxis,
    semiMinorAxis: fakeLayerAttrs.semiMinorAxis,
    speed: fakeLayerAttrs.speed,
    circleCount: fakeLayerAttrs.circleCount,
    config: fakeLayerAttrs,
    scale: 1,
  };
  sceneStore.selLayer.attr = attr;
  const entity = cimInstance.entityApi.getEntity(layerName);
  cimInstance.api.setOrbitControlByInstance(entity, layerName, (backAttr: any) => {
    if (!sceneStore.selLayer.attr) return;
    sceneStore.selLayer.attr.position = [
      backAttr.cartographic.longitude,
      backAttr.cartographic.latitude,
      round(backAttr.cartographic.height, 2),
    ];
    sceneStore.selLayer.attr.rotation = [
      round(backAttr.rotation.x, 2),
      round(backAttr.rotation.y, 2),
      round(backAttr.rotation.z, 2),
    ];
    sceneStore.selLayer.attr.scale = backAttr.scale.x;
  });
  cimInstance.api.changeOrbitControlMode('translation');
  sceneStore.specialEffectVisible = true;
};

// 粒子特效点击回调事件
export const entityEffectClickCallback = (e: any) => {
  const { cimInstance } = window;
  if (!e.clickObject) return;
  const sceneStore = useSceneStore();
  // 点击模型暂未实现
  // 主要用于特效打点立即弹出
  // TODO 此处暂时这么判断
  if (sceneStore.effectDotState && !e.code) return;
  if (sceneStore.selLayer) {
    destroyOrbitControl(sceneStore.selLayer);
  }
  const layerName = e.clickObject.id;
  const targetLayer = getNodeByTree(layerName, sceneStore.layerTree);
  if (!targetLayer) return;
  sceneStore.selLayer = targetLayer;
  const attr: any = {
    position: [0, 0, 0],
    scale: 0,
    scaleData: 0,
    rotation: [0, 0, 0],
  };
  sceneStore.selLayer.attr = attr;
  const entity = cimInstance.entityApi.getEntity(layerName);
  cimInstance.api.setOrbitControlByInstance(entity, layerName, (backAttr: any) => {
    if (!sceneStore.selLayer.attr) return;
    sceneStore.selLayer.attr.position = [
      backAttr.cartographic.longitude,
      backAttr.cartographic.latitude,
      round(backAttr.cartographic.height, 2),
    ];
    sceneStore.selLayer.attr.scale = backAttr.scale.x;
    if (sceneStore.selLayer.attr?.scale) {
      sceneStore.selLayer.attr.scaleData = sceneStore.selLayer.attr.scale * 100;
    }
    sceneStore.selLayer.attr.rotation = [
      round(backAttr.rotation.x, 2),
      round(backAttr.rotation.y, 2),
      round(backAttr.rotation.z, 2),
    ];
  });
  cimInstance.api.changeOrbitControlMode('translation');
  sceneStore.specialEffectVisible = true;
};

// div图层点击事件回调
export const divLayerClickCallback = (layerName: string) => {
  const sceneStore = useSceneStore();
  const targetLayer = getNodeByTree(layerName, sceneStore.layerTree);
  if (!targetLayer) return;
  sceneStore.selLayer = targetLayer;
  sceneStore.specialEffectVisible = true;
};

export const clearLayerClickCallbackMap = () => {
  layerClickCallbackMap.clear();
};

// 对于drawlabel类型无效点进行处理
export function operateInvalidPoi() {
  const { cimInstance } = window;
  const sceneStore = useSceneStore();
  for (let i = sceneStore.layerList.length - 1; i >= 0; i--) {
    if (sceneStore.layerList[i].type === 'drawlabel') {
      const result = cimInstance.api.getGraphicInfo(
        sceneStore.layerList[i].layerName,
        'poi_0_image',
        {
          properties: true,
        }
      );
      if (!result || (result && !result.properties)) {
        sceneStore.layerList.splice(i, 1);
        continue;
      }
    }
  }
  const digui = (arr: any[]) => {
    if (!arr.length) return;
    for (let i = arr.length - 1; i >= 0; i--) {
      if (arr[i].type === 'drawlabel') {
        const result = cimInstance.api.getGraphicInfo(arr[i].layerName, 'poi_0_image', {
          properties: true,
        });
        if (!result || (result && !result.properties)) {
          arr.splice(i, 1);
          continue;
        }
      } else if (arr[i].type === 'folder' && arr[i].children && arr[i].children.length) {
        digui(arr[i].children);
      }
    }
  };
  digui(sceneStore.layerTree);
}

// 挂载底座全局事件
export const addSceneEvent = () => {
  const { cimInstance } = window;
  cimInstance.eventApi.addEventListener('scene_leftclick', function (position: any) {
    cimInstance.api.cancelEdit();
  });
};

// 取消3轴
export const destroyOrbitControl = (layer: API.Scene.ILayer) => {
  const { cimInstance } = window;
  if (
    layer.layerName &&
    ['gltfmodel', 'entity', 'fake_particleSystem', 'bimModel', 'tileset', 'drawlabel'].includes(
      layer.type
    )
  ) {
    cimInstance.api.changeOrbitControlMode('');
    cimInstance.api.deleteOrbitControl(layer.layerName);
  }
};
